#define EPSILON.001
#define MAX_DIST 200.
// 用更大的迭代次数保证最远处不隆起
#define MAX_ITER 300

// 不用sin的随机数，因为是无理数在显卡上渲染后会造成不连续的情况。
float hash12(in vec2 st){
  vec3 p3=fract(vec3(st.xyx)*.1031);
  p3+=dot(p3,p3.yzx+33.33);
  return fract((p3.x+p3.y)*p3.z);
}

vec3 noise(in vec2 st){
  vec2 i=floor(st);
  vec2 f=fract(st);
  
  // Four corners in 2D of a tile
  float a=hash12(i);
  float b=hash12(i+vec2(1.,0.));
  float c=hash12(i+vec2(0.,1.));
  float d=hash12(i+vec2(1.,1.));
  
  // Cubic Hermine Curve.  Same as SmoothStep()
  vec2 u=f*f*(3.-2.*f);
  // Mix 4 coorners percentages
  
  // 设置个梯度
  vec2 du=6.*u*(1.-u);
  
  return vec3(a+(b-a)*u.x*(1.-u.y)+(c-a)*(1.-u.x)*u.y+(d-a)*u.x*u.y,du*(vec2(b-a,c-a)+(a-b-c+d)*u.yx));
}

vec2 fixUV(vec2 cood){
  return(2.*cood.xy-iResolution.xy)/min(iResolution.x,iResolution.y);
}

mat2 mat=mat2(.6,-.8,.8,.6);

float ground(vec2 p){
  float a=0.;
  float b=1.;
  vec2 d=vec2(0);
  for(int i=0;i<8;i++){
    vec3 n=noise(p);
    d+=n.yz;
    a+=b*n.x/(1.+dot(d,d));
    p=mat*p*2.;
    b*=.5;
  }
  return a;
}

float rayMarch(vec3 ro,vec3 rd){
  float t=0.;
  for(int i=0;i<MAX_ITER;i++){
    vec3 p=ro+t*rd;
    float h=p.y-ground(p.xz);
    // EPSILON * t 设置EPSILON精度由近到远变低，提高渲染效率
    if(abs(h)<EPSILON*t||t>MAX_DIST){
      break;
    }
    // t+=h;
    // 解决拉伸后瑕疵
    t+=.2*h;
  }
  return t;
}

vec3 calcNorm(vec3 p,float t){
  vec2 epsilon=vec2(.001*t,0);
  return normalize(vec3(
      ground(p.xz+epsilon.xy)-ground(p.xz-epsilon.xy),
      2.*epsilon.x,
      ground(p.xz+epsilon.yx)-ground(p.xz-epsilon.yx)
    )
  );
}

mat3 setCamera(vec3 ro,vec3 target,float cr){
  vec3 z=normalize(target-ro);
  vec3 up=normalize(vec3(sin(cr),cos(cr),0));
  vec3 x=cross(z,up);
  vec3 y=cross(x,z);
  return mat3(x,y,z);
}

vec3 render(vec2 uv){
  vec3 col=vec3(0.);
  float an=iTime*.001;
  float r=100.;
  vec2 pos2d=vec2(r*sin(an),r*cos(an));
  float h=ground(pos2d)+.1;
  vec3 ro=vec3(pos2d.x,h,pos2d.y);
  // vec3 target=vec3(0,0,10);
  vec3 target=vec3(r*sin(an+.01),h,r*cos(an+.01));
  mat3 cam=setCamera(ro,target,0.);
  
  float fl=1.;
  vec3 rd=normalize(cam*vec3(uv,fl));
  
  float t=rayMarch(ro,rd);
  
  if(t<MAX_DIST){
    vec3 p=ro+t*rd;
    vec3 n=calcNorm(p,t);
    vec3 difColor=vec3(.67,.57,.44);
    col=.2+.8*difColor*dot(n,vec3(0,1,0));
  }
  
  // return sqrt(col);
  return col;
}

void mainImage(out vec4 fragColor,in vec2 fragCoord){
  vec2 uv=fixUV(fragCoord);
  vec3 color=render(uv);
  fragColor=vec4(color,1.);
}